package com.putao.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.putao.base.BaseService;
import com.putao.base.BaseWrapper;
import com.putao.constants.ColorList;
import com.putao.constants.Constants;
import com.putao.domain.Bill;
import com.putao.domain.Category;
import com.putao.enums.Color;
import com.putao.error.BusinessException;
import com.putao.mapper.CategoryMapper;
import com.putao.service.BillService;
import com.putao.service.CategoryService;
import com.putao.utils.BigDecimalUtil;
import com.putao.utils.SnowflakeConfig;
import com.putao.utils.ThreadLocalUtil;
import com.putao.vo.BaseVo;
import com.putao.vo.CategoryVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author fuhehuang
 * @email 2628279194@qq.com
 */
@Service
public class CategoryServiceImpl extends ServiceImpl<CategoryMapper, Category> implements CategoryService, BaseService<Category> {

    @Autowired
    private SnowflakeConfig snowflakeConfig;
    @Autowired
    private BillService billService;

    @Override
    public Category saveCategory(CategoryVo categoryVo) {
        Category category = new Category();
        BeanUtils.copyProperties(categoryVo, category);
        try {
            checkColumnIsEmpty(category, "name", "icon", "colorIndex", "type", "accountBookId");
            if (Constants.CATEGORY_TYPE_PAY.equals(category.getType())) {
                checkColumnIsEmpty(category, "budget");
            } else {
                category.setBudget(null);
            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(e.getMessage());
        }
        // 检查名称，图标不能重复
        this.checkIsEmptyAndRepeat(null, new QueryWrapper<>(), category, "name", "名称重复了", "名称不能为空", "account_book_id", category.getAccountBookId());
        this.checkIsEmptyAndRepeat(null, new QueryWrapper<>(), category, "icon", "图标重复了", "图标不能为空", "account_book_id", category.getAccountBookId());
        category.insertInit(snowflakeConfig.snowflakeId());
        category.setBalance(BigDecimal.ZERO);
        Color color = ColorList.colorList.get(categoryVo.getColorIndex());
        if (ObjectUtil.isNotEmpty(color)) {
            category.setIconColor(color.getIconColor());
            category.setCircularColor(color.getCircularColor());
            category.setLightColor(color.getLightColor());
            category.setBgcColor(color.getDeepColor());
        }
        this.save(category);
        return category;
    }

    @Override
    public boolean updateCategory(Category category) {
        try {
            checkColumnIsEmpty(category, "name", "icon", "colorIndex", Constants.CATEGORY_TYPE_INCOME.equals(category.getType()) ? "budget" : "", "type", "accountBookId");
        } catch (Exception e) {
            e.printStackTrace();
            throw new BusinessException(e.getMessage());
        }
        this.checkIsRepeat(category.getId(), new QueryWrapper<>(), category, "name", "名称重复了", "account_book_id", category.getAccountBookId());
        this.checkIsRepeat(category.getId(), new QueryWrapper<>(), category, "icon", "图标重复了","account_book_id", category.getAccountBookId());
        category.updateInit();
        Color color = ColorList.colorList.get(category.getColorIndex());
        if (ObjectUtil.isNotEmpty(color)) {
            category.setIconColor(color.getIconColor());
            category.setCircularColor(color.getCircularColor());
            category.setLightColor(color.getLightColor());
            category.setBgcColor(color.getDeepColor());
        }
        this.updateById(category);
        return true;
    }

    @Override
    public List<CategoryVo> selectListByPhone(BaseVo baseVo, String userId, QueryWrapper<Category> wrapper) {
        wrapper.orderByDesc("create_time");
        List<Category> categoryList = this.list(wrapper);
        if (CollectionUtil.isEmpty(categoryList)) {
            return new ArrayList<>();
        }
        List<CategoryVo> categoryVoList = new ArrayList<>();
        // 查出对应的账单信息，并计算出对应的总数
        List<Bill> billList = billService.list(new BaseWrapper<Bill>().init(userId));
        Map<String, List<Bill>> categoryIdBillListMap = new HashMap<>();
        if (CollectionUtil.isNotEmpty(billList)) {
            categoryIdBillListMap = billList.stream().collect(Collectors.groupingBy(Bill::getCategoryId));
        }
        for (Category category : categoryList) {
            CategoryVo categoryVo = new CategoryVo();
            BeanUtils.copyProperties(category, categoryVo);
            List<Bill> bills = categoryIdBillListMap.get(category.getId());
//            if (CollectionUtil.isNotEmpty(bills)) {
//                categoryVo.setBalance(bills.stream().map(Bill::getMoney).reduce(BigDecimal::add).orElse(BigDecimal.ZERO));
//            }
            categoryVo.setBillList(bills);
            categoryVoList.add(categoryVo);
        }
        return categoryVoList;

    }

    @Override
    public void updateMoney(String userId) {
        List<Category> categoryList = this.list(new BaseWrapper<Category>().init(userId));
        if (CollectionUtil.isEmpty(categoryList)) {
            return;
        }
        List<String> categoryIdList = categoryList.stream().map(Category::getId).collect(Collectors.toList());
        List<Bill> billList = billService.list(new BaseWrapper<Bill>().init(userId).in("category_id", categoryIdList));
        if (CollectionUtil.isEmpty(billList)) {
            return;
        }
        Map<String, List<Bill>> categoryIdBillListMap = billList.stream().collect(Collectors.groupingBy(Bill::getCategoryId));
        for (Category category : categoryList) {
            List<Bill> bills = categoryIdBillListMap.get(category.getId());
            if (CollectionUtil.isEmpty(bills)) {
                continue;
            }
            // 根据类型分组
            Map<String, BigDecimal> typeNumMap = bills.stream().collect(Collectors.toMap(Bill::getType, Bill::getMoney, BigDecimal::add));
            // 总数
            BigDecimal totalNum = BigDecimal.ZERO;
            if (CollectionUtil.isNotEmpty(typeNumMap)) {
                for (String type : typeNumMap.keySet()) {
                    if (Constants.BILL_TYPE_PAY.equals(type)) {
                        totalNum = totalNum.subtract(typeNumMap.get(type));
                    } else {
                        totalNum = totalNum.add(typeNumMap.get(type));
                    }
                }
            }
            category.setBalance(BigDecimalUtil.abs(totalNum));
        }
        this.updateBatchById(categoryList);
    }

    @Override
    public List<Category> getForPayTypeByAccountBookId(String accountBookId) {
        QueryWrapper<Category> qw = new BaseWrapper<Category>().init(ThreadLocalUtil.getUserId());
        qw.eq("account_book_id", accountBookId).eq("type", Constants.CATEGORY_TYPE_PAY);
        return  this.list(qw);
    }
}
